//
//  UIViewController+ATKit.m
//  Postre
//
//  Created by CoderLT on 2017/5/22.
//  Copyright © 2017年 CoderLT. All rights reserved.
//

#import "UIViewController+ATKit.h"
#import "ATHightlightButton.h"

YYSYNTH_DUMMY_CLASS(UIViewController_ATKit)

static char at_prefersNavigationBarHiddenKey = '\0';
static char at_showBottomBarWhenPushedKey = '\0';
static char at_statisticsTitleKey = '\0';
@implementation UIViewController (ATKit)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        
        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(at_viewWillAppear:);
        
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (success) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
        
        // viewDidAppear
        originalSelector = @selector(viewDidAppear:);
        swizzledSelector = @selector(at_viewDidAppear:);
        
        originalMethod = class_getInstanceMethod(class, originalSelector);
        swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (success) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
        
        // viewWillDisappear
        originalSelector = @selector(viewWillDisappear:);
        swizzledSelector = @selector(at_viewWillDisappear:);
        
        originalMethod = class_getInstanceMethod(class, originalSelector);
        swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (success) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}
- (void)at_viewWillAppear:(BOOL)animated {
    [self at_viewWillAppear:animated];

    if (self.navigationController
        && self.parentViewController == self.navigationController
        && objc_getAssociatedObject(self, &at_prefersNavigationBarHiddenKey)) {
        [self.navigationController setNavigationBarHidden:self.at_prefersNavigationBarHidden animated:animated];
    }
}

- (void)at_viewDidAppear:(BOOL)animated {
    [self at_viewDidAppear:animated];
}

- (void)at_viewWillDisappear:(BOOL)animated {
    [self at_viewWillDisappear:animated];
}

- (BOOL)at_prefersNavigationBarHidden {
    return [objc_getAssociatedObject(self, &at_prefersNavigationBarHiddenKey) boolValue];
}
- (void)setAt_prefersNavigationBarHidden:(BOOL)hidden {
    objc_setAssociatedObject(self, &at_prefersNavigationBarHiddenKey, @(hidden), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)at_showBottomBarWhenPushed {
    return [objc_getAssociatedObject(self, &at_showBottomBarWhenPushedKey) boolValue];
}
- (void)setAt_showBottomBarWhenPushed:(BOOL)show {
    objc_setAssociatedObject(self, &at_showBottomBarWhenPushedKey, @(show), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)at_statisticsTitle {
    return objc_getAssociatedObject(self, &at_statisticsTitleKey) ?: self.navigationItem.title;
}
- (void)setAt_statisticsTitle:(NSString *)at_statisticsTitle {
    objc_setAssociatedObject(self, &at_statisticsTitleKey, at_statisticsTitle, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (void)setNavItemTitle:(NSString *)title {
    self.navigationItem.title = title;
}
- (void)setBackItem:(UIImage *)image {
    return [self setBackItem:image closeItem:image];
}
- (void)setBackItem:(UIImage *)image closeItem:(UIImage *)closeImage {
    if (self.navigationController.viewControllers.count == 1 && self.presentingViewController) {
        self.navigationItem.leftBarButtonItem = [self navItemWithImage:closeImage
                                                                 title:(closeImage ? nil : @"ㄨ")
                                                                action:@selector(goBack)];
    }
    else if ((self.navigationController.viewControllers.count > 1 || (!self.navigationController && !self.parentViewController))) {
        self.navigationItem.leftBarButtonItem =  [self navItemWithImage:image
                                                                  title:(image ? nil : @"ㄑ")
                                                                 action:@selector(goBack)];
    }
    else {
        self.navigationItem.leftBarButtonItem = nil;
        self.navigationItem.hidesBackButton = YES;
    }
    ((UIButton *)self.navigationItem.leftBarButtonItem.customView).contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
}
- (void)showNavTitle:(NSString *)title backItem:(BOOL)show {
    [self setAt_prefersNavigationBarHidden:NO];
    [self setNavItemTitle:title];
    if (show) {
        [self setBackItem:[UIImage imageNamed:@"nav_back"] closeItem:[UIImage imageNamed:@"nav_close"]];
    }
    else {
        self.navigationItem.leftBarButtonItem = nil;
        self.navigationItem.hidesBackButton = YES;
    }
}
- (UIBarButtonItem *)navItemWithImage:(UIImage *)image action:(SEL)action {
    return [self navItemWithImage:image title:nil color:nil action:action];
}
- (UIBarButtonItem *)navItemWithTitle:(NSString *)title action:(SEL)action {
    return [self navItemWithImage:nil title:title color:nil action:action];
}
- (UIBarButtonItem *)navItemWithTitle:(NSString *)title color:(UIColor *)color action:(SEL)action {
    return [self navItemWithImage:nil title:title color:color action:action];
}
- (UIBarButtonItem *)navItemWithImage:(UIImage *)image title:(NSString *)title action:(SEL)action {
    return [self navItemWithImage:image title:title color:nil action:action];
}
- (UIBarButtonItem *)navItemWithImage:(UIImage *)image title:(NSString *)title color:(UIColor *)color action:(SEL)action {
    return [self navItemWithImage:image title:title color:color target:self action:action];
}
- (UIBarButtonItem *)navItemWithImage:(UIImage *)image title:(NSString *)title color:(UIColor *)color target:(id)target action:(SEL)action {
    if (image && title.length <= 0) {
        return [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:action];
    }
    else if (!image && title.length > 0) {
        UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStylePlain target:self action:action];
        if (color) {
            [item setTitleTextAttributes:@{NSForegroundColorAttributeName : color} forState:UIControlStateNormal];
            [item setTitleTextAttributes:@{NSForegroundColorAttributeName : [color colorWithAlphaComponent:0.7f]} forState:UIControlStateHighlighted];
            [item setTitleTextAttributes:@{NSForegroundColorAttributeName : [color colorWithAlphaComponent:0.5f]} forState:UIControlStateDisabled];
        }
        return item;
    }
    else {
        return [[UIBarButtonItem alloc] initWithCustomView:[ATBarButton buttonWithImage:image title:title color:color target:target action:action]];
    }
}
- (void)setNavRightItemWithImage:(UIImage *)image action:(SEL)action {
    [self setNavRightItemWithImage:image title:nil color:nil action:action];
}
- (void)setNavRightItemWithTitle:(NSString *)title action:(SEL)action {
    [self setNavRightItemWithImage:nil title:title color:nil action:action];
}
- (void)setNavRightItemWithTitle:(NSString *)title color:(UIColor *)color action:(SEL)action {
    [self setNavRightItemWithImage:nil title:title color:color action:action];
}
- (void)setNavRightItemWithImage:(UIImage *)image title:(NSString *)title action:(SEL)action {
    [self setNavRightItemWithImage:image title:title color:nil action:action];
}
- (void)setNavRightItemWithImage:(UIImage *)image title:(NSString *)title color:(UIColor *)color action:(SEL)action {
    self.navigationItem.rightBarButtonItem = [self navItemWithImage:image title:title color:color action:action];
}

- (void)goBack {
    [self goBack:YES];
}
- (void)goBack:(BOOL)animated {
    @try {
        if (self.navigationController.viewControllers.count > 1) {
            [self.navigationController popViewControllerAnimated:animated];
        }
        else if (self.presentingViewController) {
            [self dismissViewControllerAnimated:animated completion:nil];
            [self.view endEditing:YES];
        }
    } @catch (NSException *exception) {
        DLog(@"%@", exception);
    }
}
- (void)dismissOrPopToRootControlelr {
    [self dismissOrPopToRootController:YES];
}
- (void)dismissOrPopToRootController:(BOOL)animated {
    @try {
        if (self.presentingViewController) {
            [self dismissViewControllerAnimated:animated completion:nil];
            [self.view endEditing:YES];
        }
        else if (self.navigationController.viewControllers.count > 1) {
            [self.navigationController popToRootViewControllerAnimated:animated];
        }
    } @catch (NSException *exception) {
        DLog(@"%@", exception);
    }
}


+ (UIViewController *)rootTopPresentedController {
    return [self rootTopPresentedControllerWihtKeys:nil];
}
+ (UIViewController *)rootTopPresentedControllerWihtKeys:(NSArray<NSString *> *)keys {
    return [[[[UIApplication sharedApplication] delegate] window].rootViewController topPresentedControllerWihtKeys:keys];
}
- (UIViewController *)topPresentedController {
    return [self topPresentedControllerWihtKeys:nil];
}
- (UIViewController *)topPresentedControllerWihtKeys:(NSArray<NSString *> *)keys {
    keys = keys ?: @[@"centerViewController", @"contentViewController"];
    
    UIViewController *rootVC = self;
    if ([rootVC isKindOfClass:[UITabBarController class]]) {
        UITabBarController *tab = (UITabBarController *)rootVC;
        UIViewController *vc = tab.selectedViewController ?: tab.childViewControllers.firstObject;
        if (vc) {
            return [vc topPresentedControllerWihtKeys:keys];
        }
    }
    
    for (NSString *key in keys) {
        if ([rootVC respondsToSelector:NSSelectorFromString(key)]) {
            UIViewController *vc;
            @try {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                vc = [rootVC performSelector:NSSelectorFromString(key)];
#pragma clang diagnostic pop
            } @catch (NSException *exception) {
            }
            if ([vc isKindOfClass:[UIViewController class]]) {
                return [vc topPresentedControllerWihtKeys:keys];
            }
        }
    }
    
    while (rootVC.presentedViewController && !rootVC.presentedViewController.isBeingDismissed) {
        rootVC = rootVC.presentedViewController;
    }
    
    if ([rootVC isKindOfClass:[UINavigationController class]]) {
        rootVC = ((UINavigationController *)rootVC).topViewController;
    }
    
    return rootVC;
}

- (NSArray<UIViewController *> *)optimizeVcs:(NSArray<UIViewController *> *)vcs {
    return [self optimizeVcs:vcs maxCount:1];
}
- (NSArray<UIViewController *> *)optimizeVcs:(NSArray<UIViewController *> *)vcs maxCount:(NSUInteger)count {
    NSMutableArray *vcArray = [NSMutableArray arrayWithArray:vcs];
    [vcArray addObject:self];
    for (UIViewController *vc in vcArray.reverseObjectEnumerator) {
        if ([vc isKindOfClass:[self class]]) {
            if (count) {
                count--;
            }
            else {
                [vcArray removeObject:vc];
            }
        }
    }
    return vcArray.copy;
}
@end
